package show.me.the.money.config.reportSchema.define;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.Element;

import show.me.the.money.config.reportSchema.ReportDefine;
import show.me.the.money.config.reportSchema.ReportDefineFactory;
import show.me.the.money.config.schema.SchemaItem;
import show.me.the.money.dictionary.Dictionaries;
import show.me.the.money.dictionary.Dictionary;
import show.me.the.money.util.ConfigValueParser;


public class ReportSchemaLevel extends ReportSchema {
	private static Log logger = LogFactory.getLog(ReportSchemaLevel.class);

	@SuppressWarnings({ "deprecation", "unchecked" })
	public void setDefineDoc(Document doc) {
		Element root = doc.getRootElement();
		id = root.attributeValue("id", "");
		title = root.attributeValue("title", "");

		Element cnd = root.element("condition");
		if (cnd != null) {
			try {
				if(cnds == null){
					cnds = jsonMapper.readValue(cnd.getText().replaceAll("\'", "\""),List.class);
				}
				else{
					if(cnds.get(0).equals("and")){
						cnds.add(jsonMapper.readValue(cnd.getText().replaceAll("\'", "\""),List.class));
					}
					else{
						List o = new ArrayList();
						o.add("and");
						o.add(cnds);
						o.add(jsonMapper.readValue(cnd.getText().replaceAll("\'", "\""),List.class));
						cnds = o;
					}
				}
			}catch (Exception e) {
				logger.error("parse reportCondition failed:", e);
			}
		}
		List<Element> els = root.selectNodes("queryArgs/arg");
		Element rule=root.element("rule");
		if(rule==null){
			logger.error("rule node is undefined");
			return;
		}
		int i = 0;
		String ruleId=rule.attributeValue("id");
		String ruleExpr = rule.attributeValue("expr");
		String ruleDic= rule.attributeValue("dic");
		String rulePara=rule.attributeValue("para");
		if(rulePara==null){
			rulePara=ruleExpr;
		}
		if(ruleExpr==null){
			ruleExpr=ruleId;
		}
		String defaultValue = "";
		for (Element el : els) {
			SchemaItem si = new SchemaItem(el, i);
			if (si.getId().equals(ruleExpr)) {
				defaultValue = ConfigValueParser.parse(si.getDefaultValue(),
						ctx);
			}
			queryArgs.add(si);
			i++;
		}
		
		if(ruleExpr==null){
			logger.error("missing ruleExpr");
			return;
		}
		
		els = root.elements("define");

		int startRenderIndex = 0;
		String ruleLength= (String) ctx.get("q."+rulePara);
		if(ruleLength==null){
			String ruleValue = (String) ctx.get("q." + ruleId);
			if (ruleValue == null) {
				ruleValue = defaultValue;
			}
			Dictionary dic = Dictionaries.instance().getDic(ruleDic+"Level");
			if(dic == null){
				logger.error("dic[" + ruleDic + "Level] not found");
				return;
			}
			ruleLength=dic.getItem(String.valueOf(ruleValue.length())).getProperty(rulePara);
		}
		
		for (Element el : els) {
			List<Element> headers = el.selectNodes("headers/item");
			for (Element h : headers) {
				if (h.attributeValue("id").equals(ruleId)) {
					h.addAttribute("expr",
							"substring(" + ruleExpr + ",1," +ruleLength+ ")");
					break;
				}
			}
			
			Element sortel=(Element)el.selectSingleNode("sort");
			if(sortel!=null && sortel.attributeValue("id").equals(ruleId)){
				sortel.addAttribute("id", "substring(" + ruleExpr + ",1," +ruleLength+ ")");
			}
			
			List nextLevelCnd=null;
			try {
				String ruleText=rule.getText();
				if(ruleText!=null){
					nextLevelCnd = jsonMapper.readValue(ruleText.replaceAll("'", "\"").
							replace("{0}",ruleLength), List.class);
				}
			} catch (Exception e1) {
				logger.error("parse reportCondition failed:",e1);
			}
			if(nextLevelCnd!=null){
				if (cnds == null) {
					cnds = nextLevelCnd;
				} else {
					if (cnds.get(0).equals("and")) {
						cnds.add(nextLevelCnd);
					} else {
						List o = new ArrayList();
						o.add("and");
						o.add(cnds);
						o.add(nextLevelCnd);
						cnds = o;
					}
				}
			}
			
			ReportDefine define = ReportDefineFactory.createInstance(el,
					startRenderIndex);
			define.setReportSchema(this);
			define.setQueryArgs(queryArgs);
			startRenderIndex += define.getHeaderCount();
			if (cnds != null) {
				define.addCondition(cnds);
			}
			defines.add(define);
		}

		Element el = root.element("digger");
		if (el != null) {
			diggers = new HashMap<String, String>();
			els = el.elements();
			for (Element dig : els) {
				diggers.put(dig.attributeValue("match"),
						dig.attributeValue("target"));
			}
		}

		el = root.element("chart");
		if (el != null) {
			chartInfo = new HashMap<String, String>();
			chartInfo.put("template", el.attributeValue("template"));
			chartInfo.put("chartType", el.attributeValue("chartType"));
			chartInfo.put("limit", el.attributeValue("limit"));
		}

	}
}
